/**
 * 2014-4-6 上午12:15:35
 * IndUX
 */
package com.indux.prefset.db;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.AudioManager;

import com.indux.prefset.db.constants.DataCategory;
import com.indux.prefset.db.constants.ParamName;
import com.indux.prefset.db.constants.TblCol;
import com.indux.prefset.db.domain.Field;
import com.indux.prefset.db.domain.Item;
import com.indux.prefset.exception.PrefSetException;
import com.indux.prefset.util.NumberUtil;
import com.indux.prefset.util.StringUtil;

/**
 * @author IndUX
 *
 */
public class DBManager
{
	static final String DATABASE_NAME = "PrefSet.db";
	static final int DATABASE_VERSION = 8;
	
	private final Context context;
	private final DBOprHelper dbOprHelper;
	private static AudioManager mAudioManager;
	
	private static final String SHARED_PREF_NAME = "PrefSetSysSetting";
	protected static final String USER_DATA_TABLE_NAME = "PREF_SET_USER_DATA";
	
	private static final String MASTER_TBL_NAME = "sqlite_master";
	
	public DBManager(Context context)
	{
		this.context = context;
		this.dbOprHelper = new DBOprHelper(context);
		
		DBManager.mAudioManager = (AudioManager) context
		        .getSystemService(Context.AUDIO_SERVICE);
		
		initData(context);
	}
	
	private void initData(Context context)
	{
		initSysData(context);
		
		SharedPreferences sharedPreferences = context
		        .getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
		
		if ((DATABASE_VERSION == sharedPreferences
		        .getInt("DATABASE_VERSION", 0))
		        && !sharedPreferences.getBoolean("FIRST_TIME_BOOT", true))
		{
			return;
		}
		
		initDefaultUserData();
		
		Editor edit = sharedPreferences.edit();
		edit.putInt("DATABASE_VERSION", DATABASE_VERSION);
		edit.putBoolean("FIRST_TIME_BOOT", false);
		edit.commit();
	}
	
	private void initSysData(Context context)
	{
	}
	
	private void initDefaultUserData()
	{
		dbOprHelper.getWritableDatabase()
		        .delete(USER_DATA_TABLE_NAME, null, null);
		
		initDefaultMode("Normal", 0.7f);
		
		initDefaultMode("Outside", 1.0f);
	}
	
	private void initDefaultMode(String name, float rate)
	{
		Item item = new Item(DataCategory.USER_DATA, name);
		
		Field field = new Field();
		field.setFieldName(ParamName.RING_MODE.getParamName());
		field.setFieldValue(String.valueOf(AudioManager.RINGER_MODE_NORMAL));
		item.addField(field);
		
		field = new Field();
		field.setFieldName(ParamName.RING_VOLUMN.getParamName());
		field.setFieldValue(NumberUtil.getString(mAudioManager
		        .getStreamMaxVolume(AudioManager.STREAM_RING) * rate));
		item.addField(field);
		
		field = new Field();
		field.setFieldName(ParamName.CALL_VOLUMN.getParamName());
		field.setFieldValue(NumberUtil.getString(mAudioManager
		        .getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL) * rate));
		item.addField(field);
		
		field = new Field();
		field.setFieldName(ParamName.SYS_VOLUMN.getParamName());
		field.setFieldValue(NumberUtil.getString(mAudioManager
		        .getStreamMaxVolume(AudioManager.STREAM_SYSTEM) * rate));
		item.addField(field);
		
		field = new Field();
		field.setFieldName(ParamName.MUSIC_VOLUMN.getParamName());
		field.setFieldValue(NumberUtil.getString(mAudioManager
		        .getStreamMaxVolume(AudioManager.STREAM_MUSIC) * rate));
		item.addField(field);
		
		this.insert(USER_DATA_TABLE_NAME, item);
	}
	
	public void insert(String tableName, Item item)
	{
		ContentValues values = new ContentValues();
		values.put(TblCol.COL_TYPE.getFieldName(), item.getType());
		values.put(TblCol.COL_NAME.getFieldName(), item.getName());
		
		SQLiteDatabase db = dbOprHelper.getWritableDatabase();
		for (Field field : item.getFields())
		{
			values.put(TblCol.COL_PARAM_NAME.getFieldName(), field
			        .getFieldName());
			values.put(TblCol.COL_PARAM_VALUE.getFieldName(), field
			        .getFieldValue());
			
			db.insert(tableName, null, values);
		}
	}
	
	public void update(String tableName, Item item)
	{
		delete(tableName, item);
		
		insert(tableName, item);
	}
	
	public void delete(String tableName, Item item)
	{
		String where = "(" + TblCol.COL_TYPE.getFieldName() + "=? and "
		        + TblCol.COL_NAME.getFieldName() + "=?)";
		SQLiteDatabase db = dbOprHelper.getWritableDatabase();
		db.delete(tableName, where, new String[] { item.getType(),
		        item.getName() });
	}
	
	public List<Item> getUserData() throws PrefSetException
	{
		List<Item> itemList = this.query(DataCategory.USER_DATA, null);
		
		return itemList;
	}
	
	public List<Item> query(String colType, String name)
	        throws PrefSetException
	{
		List<String> list = new ArrayList<String>();
		if (StringUtil.isNotEmpty(colType))
		{
			list.add(TblCol.COL_TYPE.getFieldName() + "='" + colType + "'");
		}
		
		if (StringUtil.isNotEmpty(name))
		{
			list.add(TblCol.COL_NAME.getFieldName() + "='" + name + "'");
		}
		
		String where = StringUtil.join(list, " and ");
		
		// query all id according to condition
		Cursor idCursor = dbOprHelper
		        .getReadableDatabase()
		        .query(true, USER_DATA_TABLE_NAME, new String[] {
		                TblCol.COL_TYPE.getFieldName(),
		                TblCol.COL_NAME.getFieldName() }, where, null, null, null, null, null, null);
		
		List<Item> result = new ArrayList<Item>();
		while (idCursor.moveToNext())
		{
			// query detail according to type and id
			where = TblCol.COL_TYPE.getFieldName() + "='" + colType + "' and "
			        + TblCol.COL_NAME.getFieldName() + "='"
			        + idCursor.getString(1) + "'";
			Cursor c = dbOprHelper
			        .getReadableDatabase()
			        .query(USER_DATA_TABLE_NAME, null, where, null, null, null, TblCol.COL_PARAM_NAME
			                .getFieldName());
			
			Item item = new Item(idCursor.getString(0), idCursor.getString(1));
			
			c.moveToNext();
			Field field = new Field();
			field.setFieldName(c.getString(3));
			field.setFieldValue(c.getString(4));
			item.addField(field);
			
			c.moveToNext();
			field = new Field();
			field.setFieldName(c.getString(3));
			field.setFieldValue(c.getString(4));
			item.addField(field);
			
			c.moveToNext();
			field = new Field();
			field.setFieldName(c.getString(3));
			field.setFieldValue(c.getString(4));
			item.addField(field);
			
			c.moveToNext();
			field = new Field();
			field.setFieldName(c.getString(3));
			field.setFieldValue(c.getString(4));
			item.addField(field);
			
			result.add(item);
		}
		
		return result;
	}
	
	private boolean isTableExist(String tableName)
	{
		Cursor c = dbOprHelper
		        .getReadableDatabase()
		        .query(MASTER_TBL_NAME, null, "(tbl_name=?)", new String[] { tableName }, null, null, null);
		int recordCount = c.getCount();
		c.close();
		
		// If there is no table, then create it
		if (recordCount <= 0)
		{
			return false;
		}
		
		return true;
	}
	
}
